package com.corn.tutorial.reactive.lesson1;

import com.corn.tutorial.reactive.base.Book;
import com.corn.tutorial.reactive.base.InMemoryDataSource;
import reactor.core.publisher.Flux;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author : Jim Wu
 * @version 1.0
 * @function : 使用1.8 stream流函数式变成 与 reactor获取每类图书中的价格最大的一本
 * @since : 2020/12/14 15:17
 */

public class GroupBookAndGetMaxPriceByFunctionalDemo {

    public static void main(String[] args) {
        Book[] books = InMemoryDataSource.books;
//        List<Book> maxPricesBook = getMaxPricesBookByStream(books);
//        maxPricesBook.forEach(System.out::println);
        Flux<Book> maxPricesBookByFlux = getMaxPricesBookByFlux(books);
        maxPricesBookByFlux.doOnNext(System.out::println).subscribe();

    }

    private static List<Book> getMaxPricesBookByStream(Book[] books) {
        return Arrays.stream(books).collect(Collectors.groupingBy(Book::getCategory))
                .values()
                .stream()
                .map(b -> b.stream().max(Comparator.comparing(Book::getPrice)).get())
                .collect(Collectors.toList());
//        return Arrays.stream(books).collect(Collectors.groupingBy(Book::getCategory))
//                .entrySet()
//                .stream()
//                .map(e -> e.getValue().stream()
//                        .sorted(Comparator.comparing(Book::getPrice).reversed())
//                        .findFirst()
//                        .get()
//                )
//                .collect(Collectors.toList());
    }

    private static Flux<Book> getMaxPricesBookByFlux(Book[] books) {
        return Flux.fromIterable(Arrays.asList(books))
                .collectMultimap(Book::getCategory)
                .flatMapMany(map -> Flux.fromIterable(map.entrySet())
                        .flatMap(kv -> Flux.fromIterable(kv.getValue())
                                .sort(Comparator.comparing(Book::getPrice).reversed())
                                .next()));
//        return Flux.fromIterable(Arrays.asList(books))
//                .groupBy(Book::getCategory)
//                .flatMap(e -> Flux.fromIterable(e.toIterable())
//                        .sort(Comparator.comparing(Book::getPrice).reversed())
//                        .next());
    }
}
